Skip to content

Conversation

@aadeshps-mcw
Copy link
Contributor

--Added support for SPV_EXT_image_raw10_raw12 extension.

@aadeshps-mcw aadeshps-mcw marked this pull request as draft September 22, 2025 05:23
@llvmbot
Copy link
Member

llvmbot commented Sep 22, 2025

@llvm/pr-subscribers-backend-spir-v

Author: Aadesh Premkumar (aadeshps-mcw)

Changes

--Added support for SPV_EXT_image_raw10_raw12 extension.


Full diff: https://github.com/llvm/llvm-project/pull/160032.diff

7 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp (+30)
  • (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.td (+2)
  • (modified) llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp (+3-1)
  • (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+43)
  • (modified) llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td (+3)
  • (added) llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll (+32)
  • (added) llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll (+45)
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 2abd9d36f7606..b00e7c34c09d5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1078,6 +1078,23 @@ static bool buildTernaryBitwiseFunctionINTELInst(
   return true;
 }
 
+static bool buildImageChannelDataTypeInst(const SPIRV::IncomingCall *Call,
+                                          unsigned Opcode,
+                                          MachineIRBuilder &MIRBuilder,
+                                          SPIRVGlobalRegistry *GR) {
+  if (Call->isSpirvOp())
+    return buildOpFromWrapper(MIRBuilder, Opcode, Call,
+                              GR->getSPIRVTypeID(Call->ReturnType));
+
+  auto MIB = MIRBuilder.buildInstr(Opcode)
+                 .addDef(Call->ReturnRegister)
+                 .addUse(GR->getSPIRVTypeID(Call->ReturnType));
+  for (unsigned i = 0; i < Call->Arguments.size(); ++i)
+    MIB.addUse(Call->Arguments[i]);
+
+  return true;
+}
+
 /// Helper function for building Intel's 2d block io instructions.
 static bool build2DBlockIOINTELInst(const SPIRV::IncomingCall *Call,
                                     unsigned Opcode,
@@ -2339,6 +2356,17 @@ generateTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call,
   return buildTernaryBitwiseFunctionINTELInst(Call, Opcode, MIRBuilder, GR);
 }
 
+static bool generateImageChannelDataTypeInst(const SPIRV::IncomingCall *Call,
+                                           MachineIRBuilder &MIRBuilder,
+                                           SPIRVGlobalRegistry *GR) {
+  const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
+  unsigned Opcode =
+      SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;
+  
+
+  return buildImageChannelDataTypeInst(Call, Opcode, MIRBuilder, GR);
+}
+
 static bool generate2DBlockIOINTELInst(const SPIRV::IncomingCall *Call,
                                        MachineIRBuilder &MIRBuilder,
                                        SPIRVGlobalRegistry *GR) {
@@ -2948,6 +2976,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
     return generateTernaryBitwiseFunctionINTELInst(Call.get(), MIRBuilder, GR);
   case SPIRV::Block2DLoadStore:
     return generate2DBlockIOINTELInst(Call.get(), MIRBuilder, GR);
+  case SPIRV::ImageChannelDataTypes:
+    return generateImageChannelDataTypeInst(Call.get(), MIRBuilder, GR);
   }
   return false;
 }
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
index d08560bb6565a..31cec3417b59d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
@@ -69,6 +69,7 @@ def ExtendedBitOps : BuiltinGroup;
 def BindlessINTEL : BuiltinGroup;
 def TernaryBitwiseINTEL : BuiltinGroup;
 def Block2DLoadStore : BuiltinGroup;
+def ImageChannelDataTypes : BuiltinGroup;
 
 //===----------------------------------------------------------------------===//
 // Class defining a demangled builtin record. The information in the record
@@ -1445,6 +1446,7 @@ defm : DemangledImageQueryBuiltin<"get_image_array_size", OpenCL_std, 3>;
 
 defm : DemangledNativeBuiltin<"get_image_num_samples", OpenCL_std, ImageMiscQuery, 1, 1, OpImageQuerySamples>;
 defm : DemangledNativeBuiltin<"get_image_num_mip_levels", OpenCL_std, ImageMiscQuery, 1, 1, OpImageQueryLevels>;
+defm : DemangledNativeBuiltin<"get_image_channel_data_type", OpenCL_std, ImageChannelDataTypes, 1, 1, OpImageQueryFormat>;
 
 //===----------------------------------------------------------------------===//
 // Class defining a "convert_destType<_sat><_roundingMode>" call record for
diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index e7da5504b2d58..4526468be014d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -147,7 +147,9 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
         {"SPV_KHR_float_controls2",
          SPIRV::Extension::Extension::SPV_KHR_float_controls2},
         {"SPV_INTEL_tensor_float32_conversion",
-         SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion}};
+         SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion},
+        {"SPV_EXT_image_raw10_raw12",
+         SPIRV::Extension::Extension::SPV_EXT_image_raw10_raw12}};
 
 bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
                                   StringRef ArgValue,
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 8039cf0c432fa..45be657547ed0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1432,6 +1432,49 @@ void addInstrRequirements(const MachineInstr &MI,
     }
     break;
   }
+  case SPIRV::OpImageQueryFormat: {
+    Register ResultReg = MI.getOperand(0).getReg();
+    const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
+    static const unsigned CompareOps[] = {
+        SPIRV::OpIEqual,       SPIRV::OpINotEqual,
+        SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
+        SPIRV::OpULessThan,    SPIRV::OpULessThanEqual,
+        SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
+        SPIRV::OpSLessThan,    SPIRV::OpSLessThanEqual};
+
+    auto CheckAndAddExtension = [&](int64_t ImmVal) {
+      if (ImmVal == 4323 || ImmVal == 4324) {
+        if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
+          Reqs.addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
+        else
+          report_fatal_error("This requires the "
+                             "SPV_EXT_image_raw10_raw12 extension");
+      }
+    };
+
+    for (MachineInstr &UseInst : MRI.use_instructions(ResultReg)) {
+      unsigned Opc = UseInst.getOpcode();
+
+      if (Opc == SPIRV::OpSwitch) {
+        for (const MachineOperand &Op : UseInst.operands())
+          if (Op.isImm())
+            CheckAndAddExtension(Op.getImm());
+      }
+      else if (llvm::is_contained(CompareOps, Opc)) {
+        for (unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
+          Register UseReg = UseInst.getOperand(i).getReg();
+          MachineInstr *ConstInst = MRI.getVRegDef(UseReg);
+          if (ConstInst && ConstInst->getOpcode() == SPIRV::OpConstantI) {
+            int64_t ImmVal = ConstInst->getOperand(2).getImm();
+            if (ImmVal)
+              CheckAndAddExtension(ImmVal);
+          }
+        }
+      }
+    }
+    break;
+  }
+
   case SPIRV::OpGroupNonUniformShuffle:
   case SPIRV::OpGroupNonUniformShuffleXor:
     Reqs.addCapability(SPIRV::Capability::GroupNonUniformShuffle);
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index d2824ee2d2caf..51ddafa08663f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -382,6 +382,7 @@ defm SPV_INTEL_2d_block_io : ExtensionOperand<122, [EnvOpenCL]>;
 defm SPV_INTEL_int4 : ExtensionOperand<123, [EnvOpenCL]>;
 defm SPV_KHR_float_controls2 : ExtensionOperand<124, [EnvVulkan, EnvOpenCL]>;
 defm SPV_INTEL_tensor_float32_conversion : ExtensionOperand<125, [EnvOpenCL]>;
+defm SPV_EXT_image_raw10_raw12 :ExtensionOperand<126, [EnvOpenCL]>;
 
 //===----------------------------------------------------------------------===//
 // Multiclass used to define Capabilities enum values and at the same time
@@ -1078,6 +1079,8 @@ defm HalfFloat : ImageChannelDataTypeOperand<13, [Kernel]>;
 defm Float : ImageChannelDataTypeOperand<14, [Kernel]>;
 defm UnormInt24 : ImageChannelDataTypeOperand<15, [Kernel]>;
 defm UnormInt101010_2 : ImageChannelDataTypeOperand<16, [Kernel]>;
+defm UnsignedIntRaw10EXT : ImageChannelDataTypeOperand<17, [Kernel]>;
+defm UnsignedIntRaw12EXT : ImageChannelDataTypeOperand<18, [Kernel]>;
 
 //===----------------------------------------------------------------------===//
 // Multiclass used to define ImageOperand enum values and at the same time
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll
new file mode 100644
index 0000000000000..680a74f89b1d9
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/constant_use.ll
@@ -0,0 +1,32 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_image_raw10_raw12 %s -o - | FileCheck %s 
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_EXT_image_raw10_raw12 -o - -filetype=obj | spirv-val %}
+
+; CHECK-NOT: OpExtension "SPV_EXT_image_raw10_raw12"
+
+define dso_local spir_kernel void @test_raw1012(ptr addrspace(1) noundef writeonly align 4 captures(none) %dst, i32 noundef %value) {
+entry:
+  switch i32 %value, label %sw.epilog [
+    i32 4323, label %sw.epilog.sink.split
+    i32 4324, label %sw.bb1
+  ]
+
+sw.bb1:                                           
+  br label %sw.epilog.sink.split
+
+sw.epilog.sink.split:                             
+  %.sink = phi i32 [ 12, %sw.bb1 ], [ 10, %entry ]
+  store i32 %.sink, ptr addrspace(1) %dst, align 4
+  br label %sw.epilog
+
+sw.epilog:                                        
+  %0 = add i32 %value, -4323
+  %or.cond = icmp ult i32 %0, 2
+  br i1 %or.cond, label %if.then, label %if.end
+
+if.then:                                          
+  store i32 1012, ptr addrspace(1) %dst, align 4
+  br label %if.end
+
+if.end:                                          
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll
new file mode 100644
index 0000000000000..41f6940d06782
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_image_raw10_raw12/writer.ll
@@ -0,0 +1,45 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_image_raw10_raw12 %s -o - | FileCheck %s 
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_EXT_image_raw10_raw12 -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpExtension "SPV_EXT_image_raw10_raw12"
+
+  define dso_local spir_kernel void @test_raw1012(ptr addrspace(1) noundef writeonly align 4 captures(none) %dst, target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img) {
+  entry:
+    %call = tail call spir_func i32 @_Z27get_image_channel_data_type14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img)
+    switch i32 %call, label %sw.epilog [
+      i32 4304, label %sw.epilog.sink.split
+      i32 4323, label %sw.bb1
+      i32 4324, label %sw.bb2
+    ]
+
+  sw.bb1:                                           
+    br label %sw.epilog.sink.split
+
+  sw.bb2:                                           
+    br label %sw.epilog.sink.split
+
+  sw.epilog.sink.split:                             
+    %.sink = phi i32 [ 12, %sw.bb2 ], [ 10, %sw.bb1 ], [ 8, %entry ]
+    store i32 %.sink, ptr addrspace(1) %dst, align 4
+    br label %sw.epilog
+
+  sw.epilog:                                       
+    %call3 = tail call spir_func i32 @_Z27get_image_channel_data_type14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img)
+    %cmp = icmp eq i32 %call3, 4323
+    br i1 %cmp, label %if.end7.sink.split, label %if.else
+
+  if.else:                                          
+    %call4 = tail call spir_func i32 @_Z27get_image_channel_data_type14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img)
+    %cmp5 = icmp eq i32 %call4, 4324
+    br i1 %cmp5, label %if.end7.sink.split, label %if.end7
+
+  if.end7.sink.split:                               
+    %.sink14 = phi i32 [ 1010, %sw.epilog ], [ 1212, %if.else ]
+    store i32 %.sink14, ptr addrspace(1) %dst, align 4
+    br label %if.end7
+
+  if.end7:                                         
+    ret void
+  }
+
+  declare spir_func i32 @_Z27get_image_channel_data_type14ocl_image2d_ro(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0))

@github-actions
Copy link

github-actions bot commented Sep 22, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@aadeshps-mcw aadeshps-mcw force-pushed the imageraw10 branch 2 times, most recently from 1870f40 to 9606068 Compare September 22, 2025 05:34
@aadeshps-mcw aadeshps-mcw marked this pull request as ready for review September 26, 2025 16:40
@aadeshps-mcw
Copy link
Contributor Author

Ping

Copy link
Contributor

@MrSidims MrSidims left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants